#include "fs_init_fatfs.h"
#include "sys_init.h"
#include "sys_log.h"

static device_disk_fatfs_t s_dev_disk[FF_VOLUMES] = {0};

#if FF_STR_VOLUME_ID >= 1
#ifndef FF_VOLUME_STRS
const char *VolumeStr[FF_VOLUMES] = {0};
#else
static char *VolumeStr[FF_VOLUMES] = {FF_VOLUME_STRS};
#endif
#endif

int f_disk_regist(device_disk_fatfs_t dev, const char *volume_name, int id)
{
    do
    {
        if (!dev || !volume_name)
        {
            return -1;
        }

        int exist_id = f_disk_get_id_by_name(volume_name);
        if (id < 0)
        {
            if (exist_id >= 0)
            {
                return 0;
            }

            for (int i = 0; i < FF_VOLUMES; i++)
            {
                if (!s_dev_disk[i])
                {
                    id = i;
                    break;
                }
            }
            if (id >= 0)
            {
                break;
            }
        }
        else
        {
            if (exist_id >= 0)
            {
                if (strcmp(f_disk_get_volume(id), volume_name) == 0)
                {
                    return 0;
                }
                else
                {
                    return -1;
                }
            }

            if (f_disk_get_id_by_name(volume_name) >= 0)
            {
                return 0;
            }

            if ((id < FF_VOLUMES) && !s_dev_disk[id])
            {
                break;
            }
        }
        return -1;

    } while (0);

    dev->data->id = id;

#if FF_STR_VOLUME_ID >= 1

#ifndef FF_VOLUME_STRS

#if FF_STR_VOLUME_ID == 1
    SYS_SNPRINT(dev->data->volume_str, CONFIG_MAX_VOL_NAME_LEN, "%s:", volume_name);
#endif
#if FF_STR_VOLUME_ID == 2
    SYS_SNPRINT(dev->data->volume_str, CONFIG_MAX_VOL_NAME_LEN, "/%s/", volume_name);
#endif

    strcpy(dev->data->volume_name, volume_name);
    VolumeStr[id] = dev->data->volume_name;

    for (int i = 0; i < FF_VOLUMES; i++)
    {
        if (VolumeStr[i] == 0)
        {
            VolumeStr[i] = "";
        }
    }

#else /* #ifndef FF_VOLUME_STRS */

#if FF_STR_VOLUME_ID == 1
    SYS_SNPRINT(dev->data->volume_str, CONFIG_MAX_VOL_NAME_LEN, "%s:", VolumeStr[id]);
#endif
#if FF_STR_VOLUME_ID == 2
    SYS_SNPRINT(dev->data->volume_str, CONFIG_MAX_VOL_NAME_LEN, "/%s/", VolumeStr[id]);
#endif

#endif /* #ifndef FF_VOLUME_STRS */

#else /* #if FF_STR_VOLUME_ID >= 1 */

    SYS_SNPRINT(dev->data->volume_str, CONFIG_MAX_VOL_NAME_LEN, "%d:", id);

#endif /* #if FF_STR_VOLUME_ID >= 1 */

    s_dev_disk[id] = dev;

    return 0;
}

int f_disk_unregist(const char *volume_name)
{
    int id = f_disk_get_id_by_name(volume_name);
    if (id >= 0)
    {
        f_mount(NULL, s_dev_disk[id]->data->volume_str, 0); // 取消文件系统
        VolumeStr[id] = "";
        s_dev_disk[id] = NULL;
        SYS_LOG_INF("%s fs unmount OK!\r\n", volume_name);
        return 0;
    }
    SYS_LOG_WRN("%s fs unmount ERROR!\r\n", volume_name);
    return -1;
}

int f_disk_get_id(device_disk_fatfs_t dev)
{
    for (int i = 0; i < FF_VOLUMES; i++)
    {
        if (s_dev_disk[i] == dev)
        {
            return s_dev_disk[i]->data->id;
        }
    }
    return -1;
}

int f_disk_get_id_by_name(const char *volume_name)
{
    TCHAR volume_str[CONFIG_MAX_VOL_NAME_LEN];
    strncpy(volume_str, volume_name, sizeof(volume_str) - 1);
    for (int i = 0; i < 2; i++)
    {
        for (int id = 0; id < FF_VOLUMES; id++)
        {
            if (s_dev_disk[id])
            {
                if (strcmp(s_dev_disk[id]->data->volume_str, volume_str) == 0)
                {
                    return s_dev_disk[id]->data->id;
                }
            }
        }

#if FF_STR_VOLUME_ID >= 1
#ifndef FF_VOLUME_STRS
#if FF_STR_VOLUME_ID == 1
        SYS_SNPRINT(volume_str, CONFIG_MAX_VOL_NAME_LEN, "%s:", volume_name);
#endif
#if FF_STR_VOLUME_ID == 2
        SYS_SNPRINT(volume_str, CONFIG_MAX_VOL_NAME_LEN, "/%s/", volume_name);
#endif
#else /* #ifndef FF_VOLUME_STRS */
#if FF_STR_VOLUME_ID == 1
        SYS_SNPRINT(volume_str, CONFIG_MAX_VOL_NAME_LEN, "%s:", volume_name);
#endif
#if FF_STR_VOLUME_ID == 2
        SYS_SNPRINT(volume_str, CONFIG_MAX_VOL_NAME_LEN, "/%s/", volume_name);
#endif
#endif /* #ifndef FF_VOLUME_STRS */
#else  /* #if FF_STR_VOLUME_ID >= 1 */
        SYS_SNPRINT(volume_str, CONFIG_MAX_VOL_NAME_LEN, "%s:", volume_name);
#endif /* #if FF_STR_VOLUME_ID >= 1 */
    }

    return -1;
}

device_disk_fatfs_t f_disk_get_dev(int id)
{
    for (int i = 0; i < FF_VOLUMES; i++)
        if (s_dev_disk[i] && s_dev_disk[i]->data->id == id)
            return s_dev_disk[i];
    return NULL;
}

const TCHAR *f_disk_get_volume(int id)
{
    for (int i = 0; i < FF_VOLUMES; i++)
        if (s_dev_disk[i] && s_dev_disk[i]->data->id == id)
            return s_dev_disk[i]->data->volume_str;
    return NULL;
}
